package com.ruoyi.common.utils

import com.ruoyi.common.constant.Constants
import com.ruoyi.common.constant.HttpStatus
import com.ruoyi.common.core.domain.entity.SysRole
import com.ruoyi.common.core.domain.model.LoginUser
import com.ruoyi.common.exception.ServiceException
import org.springframework.security.core.Authentication
import org.springframework.security.core.context.SecurityContextHolder
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder
import org.springframework.util.PatternMatchUtils

/**
 * 安全服务工具类
 *
 * @author ruoyi
 */
object SecurityUtils {
    @JvmStatic
    val userId: Long
        /**
         * 用户ID
         */
        get() = try {
            loginUser.userId!!
        } catch (e: Exception) {
            throw ServiceException("获取用户ID异常", HttpStatus.UNAUTHORIZED)
        }
    val deptId: Long
        /**
         * 获取部门ID
         */
        get() = try {
            loginUser.deptId!!
        } catch (e: Exception) {
            throw ServiceException("获取部门ID异常", HttpStatus.UNAUTHORIZED)
        }
    @JvmStatic
    val username: String
        /**
         * 获取用户账户
         */
        get() = try {
            loginUser.username
        } catch (e: Exception) {
            throw ServiceException("获取用户账户异常", HttpStatus.UNAUTHORIZED)
        }
    @JvmStatic
    val loginUser: LoginUser
        /**
         * 获取用户
         */
        get() = try {
            authentication?.principal as LoginUser
        } catch (e: Exception) {
            throw ServiceException("获取用户信息异常", HttpStatus.UNAUTHORIZED)
        }
    @JvmStatic
    val authentication: Authentication?
        /**
         * 获取Authentication
         */
        get() = SecurityContextHolder.getContext().authentication

    /**
     * 生成BCryptPasswordEncoder密码
     *
     * @param password 密码
     * @return 加密字符串
     */
    @JvmStatic
    fun encryptPassword(password: String?): String {
        val passwordEncoder = BCryptPasswordEncoder()
        return passwordEncoder.encode(password)
    }

    /**
     * 判断密码是否相同
     *
     * @param rawPassword 真实密码
     * @param encodedPassword 加密后字符
     * @return 结果
     */
    @JvmStatic
    fun matchesPassword(rawPassword: String?, encodedPassword: String?): Boolean {
        val passwordEncoder = BCryptPasswordEncoder()
        return passwordEncoder.matches(rawPassword, encodedPassword)
    }

    /**
     * 是否为管理员
     *
     * @param userId 用户ID
     * @return 结果
     */
    @JvmStatic
    fun isAdmin(userId: Long?): Boolean {
        return userId != null && 1L == userId
    }

    /**
     * 验证用户是否具备某权限
     *
     * @param permission 权限字符串
     * @return 用户是否具备某权限
     */
    fun hasPermi(permission: String?): Boolean {
        return hasPermi(loginUser.permissions!!, permission)
    }

    /**
     * 判断是否包含权限
     *
     * @param authorities 权限列表
     * @param permission 权限字符串
     * @return 用户是否具备某权限
     */
    fun hasPermi(authorities: Collection<String>, permission: String?): Boolean {
        return authorities.filter { str: String? -> MyStringUtils.hasText(str) }
                .any { x: String -> Constants.ALL_PERMISSION == x || PatternMatchUtils.simpleMatch(x, permission) }
    }

    /**
     * 验证用户是否拥有某个角色
     *
     * @param role 角色标识
     * @return 用户是否具备某角色
     */
    fun hasRole(role: String?): Boolean {
        val roleList = loginUser.user?.roles
        val roles = roleList?.map { obj: SysRole -> obj.roleKey }?.toMutableSet()
        return hasRole(roles, role)
    }

    /**
     * 判断是否包含角色
     *
     * @param roles 角色列表
     * @param role 角色
     * @return 用户是否具备某角色权限
     */
    fun hasRole(roles:Collection<String?>?, role: String?): Boolean {
        return roles!!
                .filter { str: String? -> MyStringUtils.hasText(str) }
                .any { x: String? -> Constants.SUPER_ADMIN == x || PatternMatchUtils.simpleMatch(x, role) }
    }
}
